package com.vip.jwt.common.utils.app;

import cn.hutool.http.HttpRequest;
import com.vip.jwt.common.exception.MyException;
import com.vip.jwt.common.utils.ConvertUtil;
import com.vip.jwt.common.utils.sign.WXSignUtil;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import java.util.*;

/**
 * App授权工具类（微信支付）
 */
public class APPWXPayUtil {

    @Getter
    private static String APP_ID;

    @Getter
    private static String APP_SECRET;

    @Getter
    private static String MCH_ID;

    @Getter
    private static String API_SECRET;

    @Getter
    private static String NOTIFY_URL;

    @Getter
    private static String REFUND_NOTIFY_URL;

    @Value("${app-wx-appid}")
    public void setAppId(String appId) {
        APP_ID = appId;
    }

    @Value("${app-wx-appsecret}")
    public void setAppSecret(String appSecret) {
        APP_SECRET = appSecret;
    }

    @Value("${wx-pay-mchid}")
    public void setMchId(String mchId) {
        MCH_ID = mchId;
    }

    @Value("${wx-pay-apisecret}")
    public void setApiSecret(String apiSecret){
        API_SECRET = apiSecret;
    }

    @Value("${wx-pay-notifyurl}")
    public void setNotifyUrl(String notifyUrl){
        NOTIFY_URL = notifyUrl;
    }

    @Value("${wx-pay-refund-notifyurl}")
    public void setRefundNotifyUrl(String refundNotifyUrl){
        REFUND_NOTIFY_URL = refundNotifyUrl;
    }

    /**
     * 统一下单
     * @param body 商品描述（例如：腾讯充值中心-QQ会员充值）
     * @param outTradeNo 商户订单号（可使用 WXSignUtil.getOutTradeNo() 获取）
     * @param totalFee 金额
     * @param ip 用户ip地址
     * @return
     */
    public static String unifiedOrder(String body,String outTradeNo,String totalFee,String ip){
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        Map<String,String> params = new HashMap<>(16);
        params.put("appid",APP_ID);
        // 商户号
        params.put("mch_id",MCH_ID);
        // 随机字符串
        params.put("nonce_str", WXSignUtil.getNonceStr());
        // 商品描述
        params.put("body",body);
        // 商户订单号
        params.put("out_trade_no", outTradeNo);
        // 标价金额
        params.put("total_fee",totalFee);
        // 终端ID
        params.put("spbill_create_ip",ip);
        // 通知地址
        params.put("notify_url",NOTIFY_URL);
        // 交易类型
        params.put("trade_type","APP");
        String sign = WXSignUtil.generateSignature(params, API_SECRET);
        params.put("sign",sign);
        String xmlStr;
        try {
            xmlStr = ConvertUtil.mapToXml(params);
        } catch (Exception e) {
            throw new MyException("Map转换Xml数据失败");
        }
        System.out.println(xmlStr);
        return HttpRequest.post(url).header("Content-Type","text/xml").body(xmlStr).execute().body();
    }

    /**
     * 获取订单信息返回给前端
     * @param prepayId prepayId在统一下单接口返回的数据里面
     * @return
     */
    public static Map<String,String> getOrderInfo(String prepayId,String nonceStr){
        Map<String,String> params = new HashMap<>(16);
        params.put("appid",APP_ID);
        params.put("partnerid",MCH_ID);
        params.put("package","Sign=WXPay");
        params.put("timestamp", WXSignUtil.getTimeStamp());
        params.put("noncestr",nonceStr);
        //数据包（统一下单接口返回的 prepay_id 参数值，格式如：prepay_id=xx）
        params.put("prepayid",prepayId);
        params.put("signtype", WXSignUtil.getSignType());
        String sign = WXSignUtil.generateSignature(params, API_SECRET);
        params.put("sign",sign);
        return params;
    }

    /**
     * 根据商户订单号查询订单
     * @param outTradeNo 商户订单号
     * @return
     */
    public static String orderQuery(String outTradeNo){
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";
        Map<String,String> params = new HashMap<>(16);
        params.put("appid",APP_ID);
        // 商户号
        params.put("mch_id",MCH_ID);
        // 随机字符串
        params.put("nonce_str", WXSignUtil.getNonceStr());
        // 商户订单号
        params.put("out_trade_no", outTradeNo);
        String sign = WXSignUtil.generateSignature(params, API_SECRET);
        params.put("sign",sign);
        String xmlStr;
        try {
            xmlStr = ConvertUtil.mapToXml(params);
        } catch (Exception e) {
            throw new MyException("Map转换Xml数据失败");
        }
        System.out.println(xmlStr);
        return HttpRequest.post(url).header("Content-Type","text/xml").body(xmlStr).execute().body();
    }

    /**
     * 根据商户订单号退款
     * @param outTradeNo 商户订单号
     * @param outRefundNo（可使用 WXSignUtil.getOutRefundNo() 获取）
     * @param totalFee 订单金额
     * @param refundFee 退款金额
     * @return
     */
    public static String refund(String outTradeNo,String outRefundNo,String totalFee,String refundFee){
        String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        Map<String,String> params = new HashMap<>(16);
        params.put("appid",APP_ID);
        // 商户号
        params.put("mch_id",MCH_ID);
        // 随机字符串
        params.put("nonce_str", WXSignUtil.getNonceStr());
        // 商户订单号
        params.put("out_trade_no", outTradeNo);
        // 商户退款单号
        params.put("out_refund_no", outRefundNo);
        // 订单金额
        params.put("total_fee", totalFee);
        // 退款金额
        params.put("refund_fee", refundFee);
        // 通知地址
        params.put("notify_url",REFUND_NOTIFY_URL);
        String sign = WXSignUtil.generateSignature(params, API_SECRET);
        params.put("sign",sign);
        String xmlStr;
        try {
            xmlStr = ConvertUtil.mapToXml(params);
        } catch (Exception e) {
            throw new MyException("Map转换Xml数据失败");
        }
        System.out.println(xmlStr);
        return WXSignUtil.postSSLRequest(url,MCH_ID,xmlStr);
    }

    /**
     * 根据商户订单号查询退款
     * 注意：没有退款成功的订单则查询不到
     * @param outTradeNo 商户订单号
     * @return
     */
    public static String refundQuery(String outTradeNo){
        String url = "https://api.mch.weixin.qq.com/pay/refundquery";
        Map<String,String> params = new HashMap<>(16);
        params.put("appid",APP_ID);
        // 商户号
        params.put("mch_id",MCH_ID);
        // 随机字符串
        params.put("nonce_str", WXSignUtil.getNonceStr());
        // 商户订单号
        params.put("out_trade_no", outTradeNo);
        String sign = WXSignUtil.generateSignature(params, API_SECRET);
        params.put("sign",sign);
        String xmlStr;
        try {
            xmlStr = ConvertUtil.mapToXml(params);
        } catch (Exception e) {
            throw new MyException("Map转换Xml数据失败");
        }
        System.out.println(xmlStr);
        return HttpRequest.post(url).header("Content-Type","text/xml").body(xmlStr).execute().body();
    }

    /**
     * 提现/转账
     * @param partnerTradeNo 商户订单号
     * @param openId 标识
     * @param amount 金额
     * @param desc 描述
     * @return
     */
    public static String transferAccounts(String partnerTradeNo,String openId,String amount,String desc){
        String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
        Map<String,String> params = new HashMap<>(16);
        params.put("mch_appid",APP_ID);
        params.put("mchid",MCH_ID);
        params.put("nonce_str",WXSignUtil.getNonceStr());
        params.put("partner_trade_no",partnerTradeNo);
        params.put("openid",openId);
        params.put("check_name","NO_CHECK");
        params.put("amount",amount);
        params.put("desc",desc);
        String sign = WXSignUtil.generateSignature(params, API_SECRET);
        params.put("sign",sign);
        String xmlStr;
        try {
            xmlStr = ConvertUtil.mapToXml(params);
        } catch (Exception e) {
            throw new MyException("Map转换Xml数据失败");
        }
        System.out.println(xmlStr);
        return WXSignUtil.postSSLRequest(url,MCH_ID,xmlStr);
    }

}

